﻿namespace Steamworks
{
    using System;
    using System.Runtime.InteropServices;

    [StructLayout(LayoutKind.Sequential)]
    public struct CSteamID : IEquatable<CSteamID>, IComparable<CSteamID>
    {
        public static readonly CSteamID Nil;
        public static readonly CSteamID OutofDateGS;
        public static readonly CSteamID LanModeGS;
        public static readonly CSteamID NotInitYetGS;
        public static readonly CSteamID NonSteamGS;
        public ulong m_SteamID;
        public CSteamID(AccountID_t unAccountID, EUniverse eUniverse, EAccountType eAccountType)
        {
            this.m_SteamID = 0L;
            this.Set(unAccountID, eUniverse, eAccountType);
        }

        public CSteamID(AccountID_t unAccountID, uint unAccountInstance, EUniverse eUniverse, EAccountType eAccountType)
        {
            this.m_SteamID = 0L;
            this.InstancedSet(unAccountID, unAccountInstance, eUniverse, eAccountType);
        }

        public CSteamID(ulong ulSteamID)
        {
            this.m_SteamID = ulSteamID;
        }

        static CSteamID()
        {
            Nil = new CSteamID();
            OutofDateGS = new CSteamID(new AccountID_t(0), 0, EUniverse.k_EUniverseInvalid, EAccountType.k_EAccountTypeInvalid);
            LanModeGS = new CSteamID(new AccountID_t(0), 0, EUniverse.k_EUniversePublic, EAccountType.k_EAccountTypeInvalid);
            NotInitYetGS = new CSteamID(new AccountID_t(1), 0, EUniverse.k_EUniverseInvalid, EAccountType.k_EAccountTypeInvalid);
            NonSteamGS = new CSteamID(new AccountID_t(2), 0, EUniverse.k_EUniverseInvalid, EAccountType.k_EAccountTypeInvalid);
        }

        public void Set(AccountID_t unAccountID, EUniverse eUniverse, EAccountType eAccountType)
        {
            this.SetAccountID(unAccountID);
            this.SetEUniverse(eUniverse);
            this.SetEAccountType(eAccountType);
            if ((eAccountType == EAccountType.k_EAccountTypeClan) || (eAccountType == EAccountType.k_EAccountTypeGameServer))
            {
                this.SetAccountInstance(0);
            }
            else
            {
                this.SetAccountInstance(1);
            }
        }

        public void InstancedSet(AccountID_t unAccountID, uint unInstance, EUniverse eUniverse, EAccountType eAccountType)
        {
            this.SetAccountID(unAccountID);
            this.SetEUniverse(eUniverse);
            this.SetEAccountType(eAccountType);
            this.SetAccountInstance(unInstance);
        }

        public void Clear()
        {
            this.m_SteamID = 0L;
        }

        public void CreateBlankAnonLogon(EUniverse eUniverse)
        {
            this.SetAccountID(new AccountID_t(0));
            this.SetEUniverse(eUniverse);
            this.SetEAccountType(EAccountType.k_EAccountTypeAnonGameServer);
            this.SetAccountInstance(0);
        }

        public void CreateBlankAnonUserLogon(EUniverse eUniverse)
        {
            this.SetAccountID(new AccountID_t(0));
            this.SetEUniverse(eUniverse);
            this.SetEAccountType(EAccountType.k_EAccountTypeAnonUser);
            this.SetAccountInstance(0);
        }

        public bool BBlankAnonAccount()
        {
            return (((this.GetAccountID() == new AccountID_t(0)) && this.BAnonAccount()) && (this.GetUnAccountInstance() == 0));
        }

        public bool BGameServerAccount()
        {
            return ((this.GetEAccountType() == EAccountType.k_EAccountTypeGameServer) || (this.GetEAccountType() == EAccountType.k_EAccountTypeAnonGameServer));
        }

        public bool BPersistentGameServerAccount()
        {
            return (this.GetEAccountType() == EAccountType.k_EAccountTypeGameServer);
        }

        public bool BAnonGameServerAccount()
        {
            return (this.GetEAccountType() == EAccountType.k_EAccountTypeAnonGameServer);
        }

        public bool BContentServerAccount()
        {
            return (this.GetEAccountType() == EAccountType.k_EAccountTypeContentServer);
        }

        public bool BClanAccount()
        {
            return (this.GetEAccountType() == EAccountType.k_EAccountTypeClan);
        }

        public bool BChatAccount()
        {
            return (this.GetEAccountType() == EAccountType.k_EAccountTypeChat);
        }

        public bool IsLobby()
        {
            return ((this.GetEAccountType() == EAccountType.k_EAccountTypeChat) && ((this.GetUnAccountInstance() & 0x40000) != 0));
        }

        public bool BIndividualAccount()
        {
            return ((this.GetEAccountType() == EAccountType.k_EAccountTypeIndividual) || (this.GetEAccountType() == EAccountType.k_EAccountTypeConsoleUser));
        }

        public bool BAnonAccount()
        {
            return ((this.GetEAccountType() == EAccountType.k_EAccountTypeAnonUser) || (this.GetEAccountType() == EAccountType.k_EAccountTypeAnonGameServer));
        }

        public bool BAnonUserAccount()
        {
            return (this.GetEAccountType() == EAccountType.k_EAccountTypeAnonUser);
        }

        public bool BConsoleUserAccount()
        {
            return (this.GetEAccountType() == EAccountType.k_EAccountTypeConsoleUser);
        }

        public void SetAccountID(AccountID_t other)
        {
            this.m_SteamID = (this.m_SteamID & 18446744069414584320L) | (((uint) other) & 0xffffffffL);
        }

        public void SetAccountInstance(uint other)
        {
            this.m_SteamID = (this.m_SteamID & 18442240478377148415L) | ((ulong) ((other & 0xfffffL) << 0x20));
        }

        public void SetEAccountType(EAccountType other)
        {
            this.m_SteamID = (this.m_SteamID & 18379190079298994175L) | ((ulong) ((((long) other) & 15L) << 0x34));
        }

        public void SetEUniverse(EUniverse other)
        {
            this.m_SteamID = (this.m_SteamID & ((ulong) 0xffffffffffffffL)) | ((ulong) ((((long) other) & 0xffL) << 0x38));
        }

        public void ClearIndividualInstance()
        {
            if (this.BIndividualAccount())
            {
                this.SetAccountInstance(0);
            }
        }

        public bool HasNoIndividualInstance()
        {
            return (this.BIndividualAccount() && (this.GetUnAccountInstance() == 0));
        }

        public AccountID_t GetAccountID()
        {
            return new AccountID_t((uint) (this.m_SteamID & 0xffffffffL));
        }

        public uint GetUnAccountInstance()
        {
            return (uint) ((this.m_SteamID >> 0x20) & ((ulong) 0xfffffL));
        }

        public EAccountType GetEAccountType()
        {
            return (EAccountType) ((int) ((this.m_SteamID >> 0x34) & ((ulong) 15L)));
        }

        public EUniverse GetEUniverse()
        {
            return (EUniverse) ((int) ((this.m_SteamID >> 0x38) & ((ulong) 0xffL)));
        }

        public bool IsValid()
        {
            if ((this.GetEAccountType() <= EAccountType.k_EAccountTypeInvalid) || (this.GetEAccountType() >= EAccountType.k_EAccountTypeMax))
            {
                return false;
            }
            if ((this.GetEUniverse() <= EUniverse.k_EUniverseInvalid) || (this.GetEUniverse() >= EUniverse.k_EUniverseMax))
            {
                return false;
            }
            if ((this.GetEAccountType() == EAccountType.k_EAccountTypeIndividual) && ((this.GetAccountID() == new AccountID_t(0)) || (this.GetUnAccountInstance() > 4)))
            {
                return false;
            }
            if ((this.GetEAccountType() == EAccountType.k_EAccountTypeClan) && ((this.GetAccountID() == new AccountID_t(0)) || (this.GetUnAccountInstance() != 0)))
            {
                return false;
            }
            if ((this.GetEAccountType() == EAccountType.k_EAccountTypeGameServer) && (this.GetAccountID() == new AccountID_t(0)))
            {
                return false;
            }
            return true;
        }

        public override string ToString()
        {
            return this.m_SteamID.ToString();
        }

        public override bool Equals(object other)
        {
            return ((other is CSteamID) && (this == ((CSteamID) other)));
        }

        public override int GetHashCode()
        {
            return this.m_SteamID.GetHashCode();
        }

        public bool Equals(CSteamID other)
        {
            return (this.m_SteamID == other.m_SteamID);
        }

        public int CompareTo(CSteamID other)
        {
            return this.m_SteamID.CompareTo(other.m_SteamID);
        }

        public static bool operator ==(CSteamID x, CSteamID y)
        {
            return (x.m_SteamID == y.m_SteamID);
        }

        public static bool operator !=(CSteamID x, CSteamID y)
        {
            return !(x == y);
        }

        public static explicit operator CSteamID(ulong value)
        {
            return new CSteamID(value);
        }

        public static explicit operator ulong(CSteamID that)
        {
            return that.m_SteamID;
        }
    }
}

